home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / network / daemons / nfs / nfs-serv.2be / nfs-serv / nfs-server-2.2beta16 / ugidd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-02-28  |  8.8 KB  |  436 lines

  1. /* UNFSD - copyright Mark A Shand, May 1988.
  2.  * This software maybe be used for any purpose provided
  3.  * the above copyright notice is retained.  It is supplied
  4.  * as is, with no warranty expressed or implied.
  5.  *
  6.  * Authors:    Mark A. Shand
  7.  *        Olaf Kirch <okir@monad.swb.de>
  8.  */
  9.  
  10. #include "site.h"
  11.  
  12. /* Only compile ugidd if nfs server has support for it. */
  13. #ifdef REAL_UGIDD
  14.  
  15. #include "system.h"
  16. #include <rpc/rpc.h>
  17. #include <rpc/pmap_clnt.h>
  18. #include <sys/ioctl.h>
  19. #include <getopt.h>
  20. #include "ugid.h"
  21. #include "logging.h"
  22. #ifdef HAVE_LIBWRAP_BUG
  23. #include <syslog.h>
  24. #endif
  25.  
  26.  
  27. static _PRO (void ugidprog_1,    (struct svc_req *rqstp, SVCXPRT *transp));
  28. static _PRO (void usage,    (void)                    );
  29.  
  30. #ifndef HAVE_RPCGEN_C
  31. #define authenticate_1_svc    authenticate_1
  32. #define name_uid_1_svc        name_uid_1
  33. #define group_gid_1_svc        group_gid_1
  34. #define uid_name_1_svc        uid_name_1
  35. #define gid_group_1_svc        gid_group_1
  36. #endif
  37.  
  38. #ifdef HOSTS_ACCESS
  39.  
  40. #define IP_HASH_MASK    0xF
  41. #define IP_HASH(a)    ((((a) >> 24) ^ ((a) >> 16) ^ ((a) >> 8) ^ (a)) & IP_HASH_MASK)
  42.  
  43. typedef struct ugid_clnt {
  44.     struct ugid_clnt    *next;
  45.     struct in_addr        clnt_addr;
  46.     char            status;
  47. } ugid_clnt;
  48.  
  49. static ugid_clnt        *clients[IP_HASH_MASK+1];
  50.  
  51. static _PRO (int  check_client,    (struct svc_req *rqstp)            );
  52. extern _PRO (int  hosts_ctl,    (char *daemon, char *host, char *user)    );
  53. static _PRO (RETSIGTYPE clnt_flush, (int sig)                );
  54.  
  55. /* libwrap.a from tcp_wrappers-7.2 references these variables when built
  56.  * with OPTIONS support, but does not define them.
  57.  */
  58. #ifdef HAVE_LIBWRAP_BUG
  59. int    deny_severity = LOG_WARNING;
  60. int    allow_severity = LOG_INFO;
  61. #endif
  62.  
  63. #else
  64. #define check_client(rqstp)    1
  65. #endif /* HOSTS_ACCESS */
  66.  
  67. static struct option longopts[] = {
  68.     { "debug", 0, 0, 'd' },
  69.     { NULL, 0, 0, 0 }
  70. };
  71.  
  72. int
  73. main(argc, argv)
  74. int    argc;
  75. char    **argv;
  76. {
  77.     SVCXPRT    *transp;
  78.     int    c, longind;
  79.     int    foreground = 0;
  80.  
  81. #ifndef HOSTS_ACCESS
  82.     fprintf(stderr,
  83.         "\n *** WARNING: This copy of ugidd has been compiled without\n"
  84.         " *** support for host_access checking. This is very risky.\n"
  85.         " *** Please consider recompiling it with access checking.\n");
  86.     sleep(1);
  87. #endif
  88.  
  89.     while ((c = getopt_long(argc, argv, "d", longopts, &longind)) != EOF) {
  90.         switch (c) {
  91.         case 'd':
  92.             foreground = 1;
  93.             enable_logging("ugid");
  94.             break;
  95.         default:
  96.             usage();
  97.         }
  98.     }
  99.  
  100.         (void)pmap_unset(UGIDPROG, UGIDVERS);
  101.  
  102.         transp = svcudp_create(RPC_ANYSOCK);
  103.         if (transp == NULL) {
  104.                 (void)fprintf(stderr, "cannot create udp service.\n");
  105.                 exit(1);
  106.         }
  107.         if (!svc_register(transp, UGIDPROG, UGIDVERS, ugidprog_1, IPPROTO_UDP)) {
  108.                 fprintf(stderr, "unable to register (UGIDPROG, UGIDVERS, UDP)\n");
  109.                 exit(1);
  110.         }
  111.  
  112.         transp = svctcp_create(RPC_ANYSOCK, 0, 0);
  113.         if (transp == NULL) {
  114.                 fprintf(stderr, "cannot create tcp service.\n");
  115.                 exit(1);
  116.         }
  117.         if (!svc_register(transp, UGIDPROG, UGIDVERS, ugidprog_1, IPPROTO_TCP)) {
  118.                 fprintf(stderr, "unable to register (UGIDPROG, UGIDVERS, TCP)\n");
  119.                 exit(1);
  120.         }
  121.  
  122.     if (!foreground) {
  123.         if ((c = fork()) > 0)
  124.             exit(0);
  125.         if (c < 0) {
  126.             fprintf(stderr, "ugidd: cannot fork: %s\n",
  127.                         strerror(errno));
  128.             exit(-1);
  129.         }
  130.         close(0);
  131.         close(1);
  132.         close(2);
  133. #ifdef HAVE_SETSID
  134.         setsid();
  135. #else
  136.         {
  137.             int fd;
  138.  
  139.             if ((fd = open("/dev/tty", O_RDWR)) >= 0) {
  140.                 ioctl(fd, TIOCNOTTY, (char *) NULL);
  141.                 close(fd);
  142.             }
  143.         }
  144. #endif
  145.     }
  146.  
  147.     log_open("ugidd", foreground);
  148.  
  149.     svc_run();
  150.     dprintf(L_ERROR, "svc_run returned\n");
  151.     return 1;
  152. }
  153.  
  154. static void
  155. usage()
  156. {
  157.     fprintf(stderr, "rpc.ugidd: [-d]\n");
  158.     exit (2);
  159. }
  160.  
  161. static void
  162. ugidprog_1(rqstp, transp)
  163.     struct svc_req *rqstp;
  164.     SVCXPRT *transp;
  165. {
  166.     union {
  167.         int authenticate_1_arg;
  168.         ugname name_uid_1_arg;
  169.         ugname group_gid_1_arg;
  170.         int uid_name_1_arg;
  171.         int gid_group_1_arg;
  172.     } argument;
  173.     char *result;
  174.     xdrproc_t xdr_argument, xdr_result;
  175.     char *(*local)();
  176.  
  177.     if (!check_client(rqstp))
  178.         return;
  179.  
  180.     switch (rqstp->rq_proc) {
  181.     case NULLPROC:
  182.         (void)svc_sendreply(transp, (xdrproc_t)xdr_void, (char *)NULL);
  183.         return;
  184.  
  185.     case AUTHENTICATE:
  186.         xdr_argument = (xdrproc_t) xdr_int;
  187.         xdr_result = (xdrproc_t) xdr_int;
  188.         local = (char *(*)()) authenticate_1_svc;
  189.         break;
  190.  
  191.     case NAME_UID:
  192.         xdr_argument = (xdrproc_t) xdr_ugname;
  193.         xdr_result = (xdrproc_t) xdr_int;
  194.         local = (char *(*)()) name_uid_1_svc;
  195.         break;
  196.  
  197.     case GROUP_GID:
  198.         xdr_argument = (xdrproc_t) xdr_ugname;
  199.         xdr_result = (xdrproc_t) xdr_int;
  200.         local = (char *(*)()) group_gid_1_svc;
  201.         break;
  202.  
  203.     case UID_NAME:
  204.         xdr_argument = (xdrproc_t) xdr_int;
  205.         xdr_result = (xdrproc_t) xdr_ugname;
  206.         local = (char *(*)()) uid_name_1_svc;
  207.         break;
  208.  
  209.     case GID_GROUP:
  210.         xdr_argument = (xdrproc_t) xdr_int;
  211.         xdr_result = (xdrproc_t) xdr_ugname;
  212.         local = (char *(*)()) gid_group_1_svc;
  213.         break;
  214.  
  215.     default:
  216.         svcerr_noproc(transp);
  217.         return;
  218.     }
  219.     bzero((char *)&argument, sizeof(argument));
  220.     if (!svc_getargs(transp, xdr_argument, &argument)) {
  221.         svcerr_decode(transp);
  222.         return;
  223.     }
  224.     result = (*local)(&argument, rqstp);
  225.     if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
  226.         svcerr_systemerr(transp);
  227.     }
  228.     if (!svc_freeargs(transp, xdr_argument, &argument)) {
  229.         (void)fprintf(stderr, "unable to free arguments\n");
  230.         exit(1);
  231.     }
  232. }
  233.  
  234. int *
  235. authenticate_1_svc(argp, rqstp)
  236.     int *argp;
  237.     struct svc_req *rqstp;
  238. {
  239.     static int res;
  240.     int    s;
  241.     struct sockaddr_in    sendaddr, destaddr;
  242.     int    dummy;
  243.     short    lport;
  244.  
  245.     bzero(&res, sizeof res);
  246.     destaddr = *svc_getcaller(rqstp->rq_xprt);
  247.     destaddr.sin_port = htons(*argp);
  248.     if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
  249.         goto bad;
  250.     setsockopt(s, SOL_SOCKET, SO_LINGER, 0, 0);
  251.     bzero((char *) &sendaddr, sizeof sendaddr);
  252.     /* find a reserved port */
  253.     lport = IPPORT_RESERVED - 1;
  254.     sendaddr.sin_family = AF_INET;
  255.     sendaddr.sin_addr.s_addr = INADDR_ANY;
  256.     for (;;)
  257.     {
  258.         sendaddr.sin_port = htons((u_short)lport);
  259.         if (bind(s, (struct sockaddr *)&sendaddr, sizeof sendaddr) >= 0)
  260.             break;
  261.         if (errno != EADDRINUSE && EADDRNOTAVAIL)
  262.             goto bad;
  263.         lport--;
  264.         if (lport <= IPPORT_RESERVED / 2)
  265.             /* give up */
  266.             break;
  267.     }
  268.     if (sendto(s, &dummy, sizeof dummy, 0,
  269.             (struct sockaddr *)&destaddr, sizeof destaddr) < 0)
  270.         goto bad;
  271.  
  272.     close(s);
  273.     res = 0;
  274.     return (&res);
  275.     bad:
  276.     close(s);
  277.     res = errno == 0 ? -1 : errno;
  278.     return (&res);
  279. }
  280.  
  281. int *
  282. name_uid_1_svc(argp, rqstp)
  283.     ugname *argp;
  284.     struct svc_req *rqstp;
  285. {
  286.     static int res;
  287.     struct passwd    *pw;
  288.  
  289.     bzero(&res, sizeof(res));
  290.     if ((pw = getpwnam(*argp)) == NULL)
  291.         res = NOBODY;
  292.     else
  293.         res = pw->pw_uid;
  294.  
  295.     return (&res);
  296. }
  297.  
  298.  
  299. int *
  300. group_gid_1_svc(argp, rqstp)
  301.     ugname *argp;
  302.     struct svc_req *rqstp;
  303. {
  304.     static int res;
  305.     struct group    *gr;
  306.  
  307.     bzero(&res, sizeof(res));
  308.     if ((gr = getgrnam(*argp)) == NULL)
  309.         res = NOBODY;
  310.     else
  311.         res = gr->gr_gid;
  312.  
  313.     return (&res);
  314. }
  315.  
  316.  
  317. ugname *
  318. uid_name_1_svc(argp, rqstp)
  319.     int *argp;
  320.     struct svc_req *rqstp;
  321. {
  322.     static ugname res;
  323.     struct passwd    *pw;
  324.  
  325.     bzero(&res, sizeof(res));
  326.     if ((pw = getpwuid(*argp)) == NULL)
  327.         res = "";
  328.     else
  329.         res = pw->pw_name;
  330.  
  331.     return (&res);
  332. }
  333.  
  334.  
  335. ugname *
  336. gid_group_1_svc(argp, rqstp)
  337.     int *argp;
  338.     struct svc_req *rqstp;
  339. {
  340.     static ugname res;
  341.     struct group    *gr;
  342.  
  343.     bzero(&res, sizeof(res));
  344.     if ((gr = getgrgid(*argp)) == NULL)
  345.         res = "";
  346.     else
  347.         res = gr->gr_name;
  348.  
  349.     return (&res);
  350. }
  351.  
  352. #ifdef HOSTS_ACCESS
  353. int
  354. check_client(rqstp)
  355.     struct svc_req *rqstp;
  356. {
  357.     struct sockaddr_in *sin;
  358.     struct in_addr       addr;
  359.     struct ugid_clnt   *up;
  360.     char           addr_s[20];
  361.     int           hash;
  362.  
  363.     sin = svc_getcaller(rqstp->rq_xprt);
  364.     addr = (struct in_addr)(sin->sin_addr);
  365.     strcpy(addr_s, inet_ntoa(addr));
  366.  
  367.     dprintf(D_UGID, "call to procedure %d from client %s\n", 
  368.                     rqstp->rq_proc, addr_s);
  369.     if (rqstp->rq_proc == NULLPROC)
  370.         return 1;
  371.  
  372.     if (ntohs(sin->sin_port) >= IPPORT_RESERVED) {
  373.         dprintf(L_ERROR,
  374.             "client %s connected from unreserved port %d\n",
  375.                     addr_s, ntohs(sin->sin_port));
  376.         return 0;
  377.     }
  378.  
  379.     hash = IP_HASH(addr.s_addr);
  380.     for (up = clients[hash]; up != NULL; up = up->next) 
  381.         if (up->clnt_addr.s_addr == addr.s_addr) break;
  382.  
  383.     if (up == NULL) {
  384.         up = (ugid_clnt *) xmalloc(sizeof(*up));
  385.         up->next = clients[hash];
  386.         clients[hash] = up;
  387.  
  388.         up->clnt_addr = addr;
  389.         up->status = hosts_ctl("ugidd", addr_s, "root");
  390.     }
  391.  
  392.     if (!up->status) {
  393.         dprintf(L_ERROR,
  394.             "access from host %s rejected\n", addr_s);
  395.     }
  396.  
  397.     return up->status;
  398. }
  399.  
  400. static RETSIGTYPE
  401. clnt_flush(int sig)
  402. {
  403.     ugid_clnt    *up, *next;
  404.     int        i;
  405.  
  406.     dprintf(D_UGID, "flushed all clients\n");
  407.     for (i = 0; i < IP_HASH_MASK+1; i++) {
  408.         for (up = clients[i]; up != NULL; up = next) {
  409.             next = up->next;
  410.             free (up);
  411.         }
  412.         clients[i] = NULL;
  413.     }
  414.     signal (SIGINT, clnt_flush);
  415. }
  416. #endif
  417.  
  418.  
  419. #else /* REAL_UGIDD */
  420.  
  421. #include <stdio.h>
  422.  
  423. int
  424. main(argc, argv)
  425.     int    argc;
  426.     char    **argv;
  427. {
  428.     fprintf(stderr, 
  429.     "\nThis copy of the Universal NFS server has been compiled without\n");
  430.     fprintf(stderr, "support for the ugidd RPC uid/gid map daemon.\n");
  431.     fprintf(stderr, "This is a dummy program.\n");
  432.     return 1;
  433. }
  434.  
  435. #endif /* REAL_UGIDD */
  436.